//
//  AlphaComposingController.m
//  vImageStudy
//
//  Created by Evan Xie on 8/13/15.
//  Copyright (c) 2015 Family Wings. All rights reserved.
//

#import <Accelerate/Accelerate.h>
#import "AlphaComposingController.h"


@interface AlphaComposingController ()

@property (weak, nonatomic) IBOutlet UIImageView *srcImageView1;
@property (weak, nonatomic) IBOutlet UIImageView *srcImageView2;
@property (weak, nonatomic) IBOutlet UIImageView *destImageView;

@property (nonatomic, strong) UIImage *srcImage1;
@property (nonatomic, strong) UIImage *srcImage2;

@end

@implementation AlphaComposingController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    _srcImage1 = [UIImage imageNamed:@"魔兽世界.jpg"];
    _srcImage2 = [UIImage imageNamed:@"lotus.png"];
    
    self.srcImageView1.image = _srcImage1;
    self.srcImageView2.image = _srcImage2;
}

- (IBAction)blendImage:(id)sender
{
#if 1
    CGImageRef topImageRef = [self.srcImage2 CGImage];
    CGImageRef bottomImageRef = [self.srcImage1 CGImage];
    
    CGDataProviderRef topProvider = CGImageGetDataProvider(topImageRef);
    CFDataRef topBitmapData = CGDataProviderCopyData(topProvider);
    
    size_t width = CGImageGetWidth(topImageRef);
    size_t height = CGImageGetHeight(topImageRef);
    size_t bytesPerRow = CGImageGetBytesPerRow(topImageRef);
    
    vImage_Buffer topBuffer = {
        .data = (void *)CFDataGetBytePtr(topBitmapData),
        .width = width,
        .height = height,
        .rowBytes = bytesPerRow,
    };
    
    CGDataProviderRef bottomProvider = CGImageGetDataProvider(bottomImageRef);
    CFDataRef bottomBitmapData = CGDataProviderCopyData(bottomProvider);
    
    vImage_Buffer bottomBuffer = {
        .data = (void *)CFDataGetBytePtr(bottomBitmapData),
        .width = width,
        .height = height,
        .rowBytes = bytesPerRow,
    };
    
    void *outBytes = malloc(height * bytesPerRow);
    vImage_Buffer outBuffer = {
        .data = outBytes,
        .width = width,
        .height = height,
        .rowBytes = bytesPerRow,
    };
    
    vImage_Error error = vImagePremultipliedAlphaBlend_ARGB8888(&topBuffer, &bottomBuffer, &outBuffer, kvImageDoNotTile);
    
    if (error) {
        NSLog(@"Error: %ld", error);
    }
    
    vImage_CGImageFormat imageFormat = {
        .bitsPerComponent = 8,
        .bitsPerPixel = 32,
        .colorSpace = NULL,
        .bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrderDefault,
        .version = 0,
        .decode = NULL,
        .renderingIntent = kCGRenderingIntentDefault
    };

    CGImageRef outCGImage = vImageCreateCGImageFromBuffer(&outBuffer, &imageFormat, NULL, NULL, kvImageNoFlags, &error);
    UIImage *outImage = [UIImage imageWithCGImage:outCGImage];
    self.destImageView.image = outImage;
    
#else
    
    CGImageRef topImageRef = self.srcImage2.CGImage;
    CGImageRef bottomImageRef = self.srcImage1.CGImage;
    
    CGDataProviderRef topProvider = CGImageGetDataProvider(topImageRef);
    CFDataRef topBitmapData = CGDataProviderCopyData(topProvider);
    
    size_t width = CGImageGetWidth(topImageRef);
    size_t height = CGImageGetHeight(topImageRef);
    size_t bytesPerRow = CGImageGetBytesPerRow(topImageRef);
    
    vImage_Buffer topBuffer = {
        .data = (void *)CFDataGetBytePtr(topBitmapData),
        .width =  width,
        .height = height,
        .rowBytes = bytesPerRow
    };
    
    CGDataProviderRef bottomProvider = CGImageGetDataProvider(bottomImageRef);
    CFDataRef bottomBitmapData = CGDataProviderCopyData(bottomProvider);
    
    width = CGImageGetWidth(bottomImageRef);
    height = CGImageGetHeight(bottomImageRef);
    bytesPerRow = CGImageGetBytesPerRow(bottomImageRef);
    
    vImage_Buffer bottomBuffer = {
        .data = (void *)CFDataGetBytePtr(bottomBitmapData),
        .width =  width,
        .height = height,
        .rowBytes = bytesPerRow
    };
    
    void *outBytes = malloc(height * bytesPerRow);
    vImage_Buffer outBuffer = {
        .data = outBytes,
        .width = width,
        .height = height,
        .rowBytes = bytesPerRow
    };
    
    vImage_Error error = vImagePremultipliedAlphaBlend_ARGB8888(&topBuffer, &bottomBuffer, &outBuffer, kvImageDoNotTile);
    if (error) {
        NSLog(@"AccelaImage: Blend error %ld", error);
    }
    
    CGContextRef destContext = CGBitmapContextCreate(&outBuffer, width, height,
                                                     8, bytesPerRow, CGColorSpaceCreateDeviceRGB(),
                                                     kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrderDefault);
    CGImageRef destRef = CGBitmapContextCreateImage(destContext);
    CGContextDrawImage(destContext, CGRectMake(0, 0, width, height), destRef);
    UIImage *blendedImage = [UIImage imageWithCGImage:destRef scale:[UIScreen mainScreen].scale orientation:self.srcImage1.imageOrientation];
    self.destImageView.image = blendedImage;
    
    
#endif

}
@end
